#include "defs.h"
#include "tools.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>


int remove_uinfo(uinfoptr goal)
    // And free its memory
{
    uinfoptr le = utable_he;
    if (le == goal)
    {
        utable_he = le->pNext;
    }
    else
    {
        uinfoptr la = le;
        for (le = le->pNext; le != goal && NULL != le; le = le->pNext)
            la = le;
        if (NULL != le) la->pNext = le->pNext;
    }
    free(goal);
    return le == goal ? 0 : -1;
}

int v4addr_eql(struct in_addr * le, struct in_addr * rt)
{
    return (*(uint32_t*)le) == (*(uint32_t*)rt);
}


static char addr[32];

int remove_client(uinfoptr le)
    // 删除操作
{
    p_time_prompt("DISCONN");
    p_v6addr(&le->v6addr);
    printf("\n");
    memset(addr, 0, 32);
    if (inet_ntop(AF_INET, &le->v4addr, addr, 32) == NULL)
    {
        perror("ip addr conv");
        return errno;
    }
    int ind;
    for (ind = 0; ind < 128; ++ind)
        if (ipaddr[ind].status &&
                strcmp(addr, ipaddr[ind].addr) == 0) break;
    if (ind < 128)
        ipaddr[ind].status = 0;
    FD_CLR(le->fd, &in_set);
    close(le->fd);
    if (remove_uinfo(le))
    {
        perror("timeout userinfo del");
        return errno;
    }
    return 0;
}


static char time_prompt[128];

int p_time_prompt(const char *he)
{
    time_t rawtime;
    time(&rawtime);
    struct tm * timeinfo = localtime(&rawtime);
    strftime(time_prompt, sizeof(time_prompt),
            "[%Y/%m/%d %H:%M:%S]", timeinfo);
    printf("%s %s: ", he, time_prompt);
    return 0;
}

static char p_addr[64];

int p_v6addr(struct in6_addr * v6)
{
    if (NULL == inet_ntop(AF_INET6, v6, p_addr, 64))
    {
        return -1;
    }
    printf("%s", p_addr);
    return 0;
}

int write_all(int fd, const void * src, int len)
{
    for (int ret; len > 0; len -= ret)
    {
        if ((ret = write(fd, src, len)) < 0)
        {
            return ret;
        }
        src += ret;
    }
    return 0;
}

int p_buf(const void * src, int head, int len)
{
    const uint8_t * buf = (uint8_t *)src;
    for (int i = 0, j = 0; i < head && i < len; ++i)
    {
        if (buf[i] < 0x10) printf("0");
        printf("%X ", buf[i]);
        if (++j == 16) 
        {
            printf("\n");
            j = 0;
        }
        if (8 == j) printf(" ");
    }
    printf("\n");
    return 0;
}

int read_msg(int fd, void * dst)
{
    struct Msg * msg = (struct Msg *)dst;
    int len = 0, t;
    while (len < 4)
    {
        if ((t = read(fd, dst, 4 - len)) < 0)
        {
            printf("len %d stop\n", len);
            return t;
        }
        len += t;
        dst += t;
    }
    int msg_len = ntohl(msg->length);
    msg->length = msg_len;
    while (len < msg_len)
    {
        if ((t = read(fd, dst, msg_len - len)) < 0)
        {
            printf("msg_len: %d; len %d stop\n", msg_len, len);
            return t;
        }
        len += t;
        dst += t;
    }
    return len;
}